package main

import (
	"fmt"
	"math"
)

/*
recover（宕机恢复）。panic异常一旦被引发就会导致程序崩溃。Go语言为开发者提供了专用于“拦截”运行时panic的内建函数recover()。

TIPS：
	1. recover()可以让进入恐慌流程的Goroutine（可当作线程理解）恢复过来并重新获得流程控制权；
	2. recover()让程序恢复必须在延迟函数中执行。换言之，recover()仅在【直接使用】在延迟函数(defer函数)上有效，就算多层嵌套中有defer依然无效；
	3. defer函数一定要在可能引发panic的语句之前定义；
	4. 在正常的程序运行过程中，调用 recover()会返回 nil，并且没有其他任何效果；
	5. 开发者应该把它作为最后的手段来使用，换言之，开发者的代码中尽量少有或者没有panic异常；
*/
func main() {

	func1()
	func2()
	func3()
	fmt.Println("主函数结束")
}

func func1() {

	fmt.Println("这是func1()")
}

func func2() {

	defer func() {
		if msg := recover(); msg != nil {
			fmt.Println("func2()恢复了，获取recover的返回值：", msg)
		}
	}()

	fmt.Println("这是 func2()")

	for i := 0; i < 10; i++ {
		fmt.Println("i: ", i+math.MaxInt64)
	}
}

func func3() {

	defer func() {
		fmt.Println("执行延迟函数")
		// TIPS：recover()仅在直接使用在延迟函数(defer函数)上有效。就算 recover() 在 defer函数的子函数中也无效
		msg := recover()
		fmt.Println("func3() 获取recover的返回值：", msg)
	}()

	fmt.Println("这是func3()")
	panic("func3() 恐慌了")
}
